import orange
import pickle
import sys
import utils
import scipy
from Categories import Categories
from Words import Words
from Files import Files
import learning as l

class RickTree(object):
    DATA_PATH = '../data/'

    def __init__(self, words, mat2):
        sys.setrecursionlimit(5000)
        self.domain = None
        self.dataMatrix = None
        self.data = None
        self.testData = None
        self.testDataMatrix = None
        self.tree = None
        self.allwords = words
        self.matrix2 = mat2
    '''
    DOMAIN
    '''
    def createDomain(self):
        utils.printTime("CREATE DOMAIN START")
        matrix2 = self.matrix2
        utils.printTime("Deserialize CLS")
        cls = utils.load('cls.ser')
        utils.printTime("Create index")
        index = matrix2.retraceWords.keys()
        for x in matrix2.retraceWords.items():
            index[x[1]] = x[0]
        keys = map(lambda x: "".join("%s" % x),cls.positions.keys())
        clusterAtt = orange.EnumVariable(name="MyCluster", values=keys)
        #clusterAtt = orange.FloatVariable(name="MyCluster")
        utils.printTime("Create attributes")
        attributes = []
        for x in index:
            attributes.append(orange.FloatVariable(name=matrix2.words[x][0]))
        attributes.append(clusterAtt)
        utils.printTime("Create domain")
        self.domain = orange.Domain(attributes)
        utils.printTime("CREATE DOMAIN STOP")

    def loadDomain(self):
        utils.printTime("LOAD DOMAIN START")
        self.domain = None
        utils.printTime("Deserialize rickDomain2")
        self.domain = utils.load('rickDomain2.ser')
        utils.printTime("LOAD DOMAIN STOP")

    def saveDomain(self):
        utils.printTime("SAVE DOMAIN START")
        utils.save('rickDomain2.ser', self.domain)
        utils.printTime("SAVE DOMAIN STOP")
    '''
    DATA
    '''
    def createData(self):
        utils.printTime("CREATE DATA START")
        utils.printTime("Deserialize reFeaturesMatrix")
        reFeaturesMatrix = utils.load('reFeaturesMatrix.ser')
        utils.printTime("Build matrix")
        mat = scipy.sparse.lil_matrix((reFeaturesMatrix.shape[0], reFeaturesMatrix.shape[1]))
        mat[:, :reFeaturesMatrix.shape[1]-1] = reFeaturesMatrix[:, range(1,reFeaturesMatrix.shape[1])]
        for i in range(reFeaturesMatrix.shape[0]):
            mat[i, reFeaturesMatrix.shape[1]-1] = reFeaturesMatrix[i, 0]
        self.dataMatrix = mat.tocsr()
        utils.printTime("Build datas")
        self.data = orange.ExampleTable(self.domain,self.dataMatrix.toarray())
        utils.printTime("CREATE DATA STOP")

    def loadData(self):
        utils.printTime("LOAD DATA START")
        self.dataMatrix = None
        self.data = None
        utils.printTime("Deserialize rickMatrix")
        self.dataMatrix = utils.load('rickMatrix.ser')
        utils.printTime("Build datas")
        self.data = orange.ExampleTable(self.domain,self.dataMatrix.toarray())
        utils.printTime("LOAD DATA STOP")

    def saveData(self):
        utils.printTime("SAVE DATA START")
        utils.save('rickMatrix.ser', self.dataMatrix)
        utils.printTime("SAVE DATA STOP")
    '''
    DATATEST
    '''
    def createDataTest(self):
        utils.printTime("CREATE DATA TEST START")
        utils.printTime("Deserialize stopWords")
        stopwords = utils.load('stopwords.ser')
        utils.printTime("Deserialize categories")
        learnCats = utils.load('categories.ser')
        utils.printTime("Deserialize cls")
        cls = utils.load('cls.ser')
        words = self.allwords
        matrix2 = self.matrix2
        folders = ('awards_1993', 'awards_1994')
        allwords = Words()
        categories = Categories()
        files = Files()
        l.readFiles(l.PATH, folders, allwords, categories, stopwords, files)
        utils.printTime("Build bags")
        fileBag = filter(lambda x: learnCats.bag.keys().__contains__(x[1][2]), files.bag.items())
        usefulWords = map(lambda x: x.name,self.domain.attributes)
        usefulWords.sort()
        utils.printTime("Map clusters")
        filesClus = map(lambda x: cls.cat2clus[learnCats.bag[x[1][2]][0]], fileBag)
        utils.printTime("Build matrix")
        testMatrix = scipy.sparse.lil_matrix((len(fileBag), len(matrix2.retraceWords)+1))
        for i in range(len(filesClus)):
            testMatrix[i, len(matrix2.retraceWords)] = filesClus[i]
            for w in fileBag[i][1][1].items():
                if usefulWords.__contains__(w[0]):
                    testMatrix[i,matrix2.retraceWords[words.bag[w[0]][0]]] = w[1]
        self.testDataMatrix = testMatrix.tocsr()
        utils.printTime("Build datas")
        self.testData = orange.ExampleTable(self.domain,self.testDataMatrix.toarray())
        utils.printTime("CREATE DATA TEST STOP")

    def loadDataTest(self):
        utils.printTime("LOAD DATA TEST START")
        self.testDataMatrix = None
        self.testData = None
        utils.printTime("Deserialize rickMatrix2")
        self.testDataMatrix = utils.load('rickMatrix2.ser')
        utils.printTime("Build datas")
        self.testData = orange.ExampleTable(self.domain,self.testDataMatrix.toarray())
        utils.printTime("LOAD DATA TEST STOP")

    def saveDataTest(self):
        utils.printTime("SAVE DATA TEST START")
        utils.save('rickMatrix2.ser', self.testDataMatrix)
        utils.printTime("SAVE DATA TEST STOP")
    '''
    TREE
    '''
    def createTree(self):
        utils.printTime("CREATE TREE START")
        self.tree = orange.TreeLearner(self.data)
        utils.printTime("CREATE TREE STOP")

    def loadTree(self):
        utils.printTime("LOAD TREE START")
        self.tree = None
        utils.printTime("Deserialize rickTree")
        self.tree = utils.load('rickTree.ser')
        utils.printTime("LOAD TREE STOP")

    def saveTree(self):
        utils.printTime("SAVE TREE START")
        utils.save('rickTree.ser', self.tree)
        utils.printTime("SAVE TREE STOP")

    def classifyBunchOfData(self,data):
        total = 0.0
        good = 0.0
        real = map(lambda x: int(x.getclass()),data)
        classified = map(lambda x: int(self.tree(x)),data)

        for i in range(len(real)):
            total = total + 1
            if real[i] == classified[i] :
                good = good + 1
        #    else:
        #        print i, "got", classified[i], "instead of", real[i]

        return good/total

    def classifyLearningData(self):
        utils.printTime("CLASSIFY LEARNING DATA START")
        val = self.classifyBunchOfData(self.data)
        print "Efficacity on training data:",val
        utils.printTime("CLASSIFY LEARNING DATA STOP")

    def classifyTestingData(self):
        utils.printTime("CLASSIFY TESTING DATA START")
        val = self.classifyBunchOfData(self.testData)
        print "Efficacity on testing data:",val
        utils.printTime("CLASSIFY TESTING DATA STOP")

    def classify(self, words):
        utils.printTime("CLASSIFY START")
        allWords = self.allwords
        matrix2 = self.matrix2
        testdata = scipy.sparse.lil_matrix((1, len(self.domain.attributes)+1))
        for word, occurence in words.iteritems():
            if word in allWords.bag:
                globalIndex = allWords.bag[word][0]
                if globalIndex in matrix2.retraceWords:
                    realIndex = matrix2.retraceWords[globalIndex]
                    testdata[0, realIndex] = occurence

        #print testdata

        testSet = orange.ExampleTable(self.domain, testdata.toarray())
        utils.printTime("CLASSIFY END")
        return self.tree(testSet[0])
